import { defineComponent, computed, ref, watchEffect, createVNode, createTextVNode, Fragment, isVNode } from 'vue';
import PageItem from './PageItem.js';
import PagePrev from './PagePrev.js';
import PageNext from './PageNext.js';
import Input from '../FormElements/Input/index.js';
import Select from '../FormElements/Select/index.js';
import Option from '../FormElements/Select/Option.js';

function _isSlot(s) {
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
}
const pages = [{
  value: 10,
  label: '10条/页'
}, {
  value: 20,
  label: '20条/页'
}, {
  value: 50,
  label: '50条/页'
}, {
  value: 100,
  label: '100条/页'
}];
const index = /* @__PURE__ */ defineComponent({
  name: "Pagination",
  props: {
    shape: {
      type: String
    },
    size: {
      type: String
    },
    current: {
      type: Number
    },
    total: {
      type: Number
    },
    pageSize: {
      type: Number
    },
    innerNear: {
      type: Number
    },
    displayedPages: {
      type: Number
    },
    startEndShowNum: {
      type: Number
    },
    showNums: {
      type: Boolean,
      default: true
    },
    mini: {
      type: Boolean
    },
    showTotal: {
      type: Boolean,
      default: true
    },
    showPage: {
      type: Boolean,
      default: true
    },
    showJumper: {
      type: Boolean,
      default: true
    },
    pages: {
      type: Array
    }
  },
  emits: ['change', 'changePageSize'],
  setup(props, {
    slots,
    emit
  }) {
    const classList = computed(() => ({
      'cm-pagination': true,
      [`cm-pagination-${props.shape}`]: props.shape,
      [`cm-pagination-${props.size}`]: props.size
    }));
    const current = () => props.current;
    const total = () => props.total ?? 0;
    const pageSize = () => props.pageSize ?? 10;
    props.innerNear ?? 2;
    props.startEndShowNum ?? 2;
    const showNums = props.showNums ?? true;
    const showTotal = props.showTotal ?? true;
    const showJumper = props.showJumper ?? true;
    const showPage = props.showPage ?? true;
    const ps = props.pages ?? pages;
    const PAGE_SHOW_MAX = 7;
    const REST_PAGE_MAX_SIZE = 5;
    const pageNum = ref(current());
    watchEffect(() => {
      if (current() != pageNum.value) {
        pageNum.value = current();
      }
    });
    const prev = () => {
      if (current() > 1) {
        _handleChange(current() - 1);
      }
    };
    const next = () => {
      if (current() < _calcPage()) {
        _handleChange(current() + 1);
      }
    };
    const gotoPage = v => {
      _handleChange(parseInt(v, 10));
    };
    const _calcPage = () => {
      // 没数据的时候默认为第一页
      if (total() === 0) {
        return 1;
      }
      return Math.floor((total() - 1) / pageSize()) + 1;
    };
    const _isValid = page => {
      return typeof page === 'number' && page >= 1;
    };

    /**
     * 页号改变
     * @method _handleChange
     * @param p 当前页号
     * @returns {*}
     * @private
     */
    const _handleChange = p => {
      let page = p;
      if (_isValid(page) && page !== current()) {
        if (page > _calcPage()) {
          page = _calcPage();
        }
        pageNum.value = page;
        emit('change', page, pageSize);
      }
    };
    const onChangePageSize = size => {
      const totalPages = Math.floor((total() - 1) / size) + 1;
      emit('changePageSize', size);
      if (current() > totalPages) {
        pageNum.value = 1;
        emit('change', 1, pageSize);
      }
    };
    function getPageNumbers() {
      let pageList = [];
      let restLeftPageList = []; // pages before ...
      let restRightPageList = []; // pages after ...
      /** Pager truncation logic (t is the total number of pages, c is the current page):
          - No need to truncate when t<=7 pages
          - When t>7
              - When c<4, the fourth is a truncation symbol (...)
              - When c=4, the sixth is the truncation symbol (...)
              - When 4<c<t-3, the second and sixth are truncation symbols (...)
              - When t-3<=c<=t, the second is the truncation symbol (...), followed by the 5th from the bottom-the 1st from the bottom
          Truncation character + number, the total number is 7
            分页器截断逻辑（t为总页数，c为当前页）：
          - t<=7 页的时候不需要截断
          - 当 t>7 时
              - 当 c<4 时，第4个为截断符号（...）
              - 当 c=4 时，第6个为截断符号（...）
              - 当 4<c<t-3 时，第2个与第6个为截断符号（...）
              - 当 t-3<=c<=t 时，第 2 个为截断符号（...），后面为倒数第5个-倒数第1个
          截断符+数字 总共个数为7个
      */
      const totalPageNum = _calcPage();
      if (totalPageNum <= PAGE_SHOW_MAX) {
        pageList = Array.from({
          length: totalPageNum
        }, (v, i) => i + 1);
        restLeftPageList = [];
        restRightPageList = [];
      } else {
        switch (true) {
          case current() < 4:
            pageList = [1, 2, 3, 4, '•••', totalPageNum - 1, totalPageNum];
            restRightPageList = Array.from({
              length: Math.min(totalPageNum - 6, REST_PAGE_MAX_SIZE)
            }, (v, i) => i + 5);
            restLeftPageList = [];
            break;
          case current() === 4:
            pageList = [1, 2, 3, 4, 5, '•••', totalPageNum];
            restRightPageList = Array.from({
              length: Math.min(totalPageNum - 6, REST_PAGE_MAX_SIZE)
            }, (v, i) => i + 6);
            restLeftPageList = [];
            break;
          case 4 < current() && current() < totalPageNum - 3:
            {
              const middleNumbers = Array.from({
                length: 3
              }, (v, i) => current() + (i - 1));
              pageList = [1].concat('•••', middleNumbers, '•••', totalPageNum);
              // length: total-(currentPage+1)-1
              restRightPageList = Array.from({
                length: Math.min(totalPageNum - current() - 2, REST_PAGE_MAX_SIZE)
              }, (v, i) => current() + i + 2);
              restLeftPageList = Array.from({
                length: Math.min(current() - 3, REST_PAGE_MAX_SIZE)
              }, (v, i) => i + 2);
              break;
            }
          case current() - 3 <= current() && current() <= totalPageNum:
            {
              const right = Array.from({
                length: 5
              }, (v, i) => totalPageNum - (4 - i));
              pageList = [1, '•••'].concat(right);
              restRightPageList = [];
              restLeftPageList = Array.from({
                length: Math.min(right[0] - 2, REST_PAGE_MAX_SIZE)
              }, (v, i) => i + 2);
              break;
            }
        }
      }
      return {
        pageList,
        restLeftPageList,
        restRightPageList
      };
    }
    function rednderItems() {
      if (!showNums) {
        return null;
      }
      const pagerList = [];
      const pageNumbers = getPageNumbers();
      const cur = current();
      pageNumbers.pageList.forEach(number => {
        const active = cur === number;
        pagerList.push(createVNode(PageItem, {
          "active": active,
          "onClick": _handleChange.bind(null, number),
          "currentIndex": number
        }, null));
      });
      return pagerList;
    }
    return () => {
      let _slot;
      return createVNode("div", {
        "class": classList.value
      }, [props.mini ? createVNode("ul", {
        "class": "cm-pagination-num-list"
      }, [createVNode(PagePrev, {
        "current": current(),
        "onClick": prev
      }, null), createVNode(Input, {
        "style": {
          width: props.size === 'small' ? '35px' : '50px'
        },
        "class": "mr-5",
        "modelValue": pageNum.value,
        "onUpdate:modelValue": $event => pageNum.value = $event,
        "size": props.size,
        "onChange": gotoPage
      }, null), createVNode("span", {
        "class": "cm-pagination-mini-pages"
      }, [createTextVNode("/ "), _calcPage()]), createVNode(PageNext, {
        "onClick": next,
        "disabled": current() === _calcPage()
      }, null)]) : createVNode(Fragment, null, [showTotal ? createVNode("span", {
        "class": "cm-pagination-text mr-5"
      }, [createTextVNode("\u5171"), total(), createTextVNode("\u6761")]) : null, createVNode("ul", {
        "class": "cm-pagination-num-list"
      }, [createVNode(PagePrev, {
        "current": current(),
        "onClick": prev
      }, null), rednderItems(), createVNode(PageNext, {
        "onClick": next,
        "disabled": current() === _calcPage()
      }, null)]), showPage ? createVNode("span", {
        "class": "cm-pagination-sizer"
      }, [createVNode(Select, {
        "modelValue": pageSize(),
        "size": props.size,
        "onChange": onChangePageSize,
        "data": ps
      }, _isSlot(_slot = ps.map(item => {
        return createVNode(Option, {
          "label": item.label,
          "value": item.value
        }, null);
      })) ? _slot : {
        default: () => [_slot]
      })]) : null, showJumper ? createVNode("span", {
        "class": "cm-pagination-jumper"
      }, [createVNode("span", {
        "class": "cm-pagination-text"
      }, [createTextVNode("\u8DF3\u81F3")]), createVNode(Input, {
        "style": {
          width: props.size === 'small' ? '35px' : '50px'
        },
        "class": "mr-5",
        "modelValue": pageNum.value,
        "onUpdate:modelValue": $event => pageNum.value = $event,
        "size": props.size,
        "onChange": gotoPage
      }, null), createVNode("span", {
        "class": "cm-pagination-text"
      }, [createTextVNode("\u9875")])]) : null])]);
    };
  }
});

export { index as default };
